# -*- coding: utf-8 -*-
# ## 4.2 回归分析-案例：大型促销活动前的销售预测
# 导入库
import pandas as pd
import numpy as np
from sklearn.linear_model import BayesianRidge, ElasticNet# 批量导入要实现的回归算法
from sklearn.svm import SVR  # SVM中的回归算法
from xgboost import XGBRegressor #需要安装
# from sklearn.ensemble.gradient_boosting import GradientBoostingRegressor  # 老版本，集成算法
from sklearn.ensemble import GradientBoostingRegressor # 新版本方法
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import explained_variance_score, mean_absolute_error, mean_squared_error, r2_score  # 批量导入指标算法
import matplotlib.pyplot as plt  # 导入图形展示库
'''
任务如下：
1.安装xgboost库
2.了解回归模型的基本含义
3.通过百度搜索，了解书中提到的5种回归模型和算法
4.了解回归模型的评估方法
5.了解回归模型预测结果与真实值的可视化对比
6.掌握回归模型的基本使用流程
'''
#读取文件
raw_data=np.loadtxt('regression.txt')
#分割自变量、因变量
x_raw,y=raw_data[:,:-1],raw_data[:,-1]

#数据标准化处理
model_as=StandardScaler()
x=model_as.fit_transform(x_raw)

#拆分数据
num=int(x.shape[0]*0.7)
#分别取钱70%用于训练，30%用于测试
x_train,x_test=x[:num,:],x[num:,:]
y_train,y_test=y[:num],y[num:]


#贝叶斯预测模型
#设置交叉验证的次数
n_folds=5
#不同模型的名称列表
model_name=['BayesianRidge','XGBR','ElasticNet','SVR','GBR']
#建立贝叶斯岭回归模型预测
model_br=BayesianRidge()
#建立XGBR对象
model_xgbr=XGBRegressor(random_state=0)
#建立弹性网络回归模型预测对象
model_etc=ElasticNet(random_state=0)
#建立支持向量机回归模型对象
model_svr=SVR(gamma='auto')
#建立梯度增强回归模型对象
model_gbr=GradientBoostingRegressor(random_state=0)
#不同回归模型对象的集合
model_list=[model_br,model_xgbr,model_etc,model_svr,model_gbr]

#各个回归模型预测的y值列表
pre_y_list=[model.fit(x_train,y_train).predict(x_test) for model in model_list]



# 模型效果评估
'''
explained_variance_score：解释回归模型的方差得分，其值取值范围是[0,1]，
越接近于1说明自变量越能解释因变量的方差变化，值越小则说明效果越差。
mean_absolute_error：平均绝对误差（Mean Absolute Error，MAE），
用于评估预测结果和真实数据集的接近程度的程度，其其值越小说明拟合效果越好。
mean_squared_error：均方差（Mean squared error，MSE），
该指标计算的是拟合数据和原始数据对应样本点的误差的平方和的均值，其值越小说明拟合效果越好。
r2_score：判定系数，其含义是也是解释回归模型的方差得分，其值取值范围是[0,1]，
越接近于1说明自变量越能解释因变量的方差变化，值越小则说明效果越差。
'''

n_sample,n_features=x.shape     #总样本量，总特征数
model_metrics_functions=[explained_variance_score,mean_absolute_error,mean_squared_error,
                         r2_score]
#回归评估列表
model_metrics_list=[[m(y_test,pre_y_list[i]) for m in model_metrics_functions] for 
                     i in range(len(model_list))]

regress_score=pd.DataFrame(model_metrics_list,index=model_name,
                           columns=['explained','mae','mse','r2'])

print('all_samples:%d \t feature:%d' % (n_sample,n_features),'\n','-'*60)

print('\n','regression_metrices:','\n','-'*60)

print(regress_score)

##效果指标评估
plt.figure(figsize=(10, 10))  # 创建画布
for i, pre_y in enumerate(pre_y_list):  # 读出通过回归模型预测得到的索引及结果
    plt.subplot(len(pre_y_list)+1,1,i+1)
    plt.plot(np.arange(len(y_test)), y_test, color='k', label='true y')  # 画出原始值的曲线
    plt.plot(np.arange(len(y_test)), pre_y_list[i], 'g--', label=model_name[i])  # 画出每条预测结果线
    plt.title('True and {} result comparison'.format(model_name[i]))  # 标题
    plt.legend(loc='upper right')  # 图例位置
    plt.tight_layout() # 自动调整子图间隔

# 模型应用
print('regression prediction','\n','-'*40)
new_point_set = [[1.05393, 0., 8.14, 0., 0.538, 5.935, 29.3, 4.4986, 4., 307., 21., 386.85, 6.58],
                 [0.7842, 0., 8.14, 0., 0.538, 5.99, 81.7, 4.2579, 4., 307., 21., 386.75, 14.67],
                 [0.80271, 0., 8.14, 0., 0.538, 5.456, 36.6, 3.7965, 4., 307., 21., 288.99, 11.69],
                 [0.7258, 0., 8.14, 0., 0.538, 5.727, 69.5, 3.7965, 4., 307., 21., 390.95,
                  11.28]]  # 要预测的新数据集
for i, new_point in enumerate(new_point_set):  # 循环读出每个要预测的数据点
    x_matrix = np.array(new_point).reshape(1, -1)
    x_scaled = model_as.transform(x_matrix)
    new_pre_y = model_xgbr.predict(x_scaled)  # 使用GBR进行预测
    print('predict for new point %d is:  %.2f' % (i + 1, new_pre_y))  # 打印输出每个数据点的预测信息
    
    
    
    
    
